home *** CD-ROM | disk | FTP | other *** search
- ///////////////////////////////////////////////////////////////////////////////
- // FILENAME: eTRTFDFileLink.h
- // SUMMARY: Implementation of an RTFD inclusion handler
- // SUPERCLASS: eTFileLink:eTImage:Object
- // INTERFACE: None
- // PROTOCOLS: None added
- // AUTHOR: Rohit Khare
- // COPYRIGHT: (c) 1994 California Institure of Technology, eText Project
- ///////////////////////////////////////////////////////////////////////////////
- // IMPLEMENTATION COMMENTS
- // Okay: here are the facts of life about NeXT's lousy RTFD implementation
- // (trust me, I know, I know the Text object every which way except from the
- // inside... grrr). It goes:
- // <space char>string<spacechar>\width<inTwips>\height<inTwips>\n}
- // (the string spec is such that you have to read it in two passes -- that's
- // why I always prefix a string by the length. (e.g. NeXT fails on a file
- // named "\width960"))
- //
- // OK, once you have the string, you have a relative filename component. Where
- // do we get the root filename component? We assume that we can reach out
- // and access() [[[view etDoc] docInfo] docPath].
- //
- // OK, now we have a fully-qualified absolute pathname. If it's a TIFF image,
- // we want to promote self to be an eTImage object encapsulating that file.
- // otherwise we want to be an eTFileLink.
- //
- // THERE ARE NO eTRTFDFileLinks IN THE SYSTEM AFTER readRichText: !!!!
- // All such instances are "promoted" by redirecting their isa pointer
- // Thus, when the file is written out, RTFD-objects will be implicitly
- // promoted to first-class eText objects.
- //
- // As an exercise for the reader: With enough cojones, it should be possible
- // to write a generic mutator to eTImage-derived objects; just make sure that
- // this object has as many bytes of storage as the larget morph target. Then
- // you could _automatically_ morph a .snd inclusion into an eTAudio :)
- ///////////////////////////////////////////////////////////////////////////////
- // HISTORY
- // 07/23/94: Created. First actual implementation.
- ///////////////////////////////////////////////////////////////////////////////
-
- #import "eTRTFDFileLink.h"
-
- @implementation eTRTFDFileLink
- + toolAwake: theApp
- {
- [theApp registerAnnotation: [eTRTFDFileLink class]
- name: "eTRTFDFileLink"
- RTFDirective: "NeXTGraphic"
- menuLabel: NULL
- menuKey: '\0'
- menuIcon: (NXImage *) nil];
- return self;
- }
- - readRichText:(NXStream *) stream forView:view
- {
- const char *const * types;
- char *ext;
- NXAtom localPath,rootPath;
- char buffer[MAXPATHLEN],ch;
- int height=0, width=0,i=0;
- char *tmp;
- BOOL foundImage=NO;
-
- // we first have to do this because this silly hack-class of ours can't
- // call [super readRichText:...] (this code is in eTImage.m)
- if (!etDoc || !theText) {
- theText = view;
- etDoc = [theText etDoc];
- [etDoc registerNotification:self];
- }
- // first fill in the buffer with all the characters up to and including \n
- while ((i < MAXPATHLEN) && ((ch = NXGetc(stream)) != '\n')) {
- buffer[i++] = ch;
- }
- buffer[i] = 0;
- // now work backward to get height.
- tmp = rindex(buffer,'\\');
- if (tmp && !strncmp(tmp, "\\height",7)) {
- //we have a valid \height entry beginning at tmp
- sscanf(tmp+7,"%d",&height);
- // now nullify the \ so we can go backwards to \width
- *tmp = 0;
- }
- // now work backward to get width.
- tmp = rindex(buffer,'\\');
- if (tmp && !strncmp(tmp, "\\width",6)) {
- //we have a valid \height entry beginning at tmp
- sscanf(tmp+6,"%d",&width);
- // now nullify the \ so we can go backwards to the string
- *tmp = 0;
- // and also consume the space character separating string from \width
- *(tmp - 1) = 0;
- }
-
- // skip the leading space -- is there one?
- tmp = buffer;
- if (*tmp == ' ') tmp++;
- localPath = NXUniqueString(tmp);
- rootPath = [[[view etDoc] docInfo] docPath];
- sprintf(buffer, "%s/%s", rootPath, localPath);
-
- // OK, now what? We have valid data.
- //NXLogError("\\NeXTGraphic got \"%s\" h:%d w:%d in \"%s\"",
- // localPath, height, width, rootPath);
-
- tmp = rindex(buffer,'/'); //get the extension of the basename.
- tmp = rindex(tmp,'.');
- if (tmp && *(++tmp)) {
- // ext is now a pointer to the extension of buffer, if there is one.
- ext = NXUniqueString(tmp); // ext of basename
- types = [NXImage imageFileTypes];
- for(i=0; (types[i] && !foundImage); i++)
- if (!strcmp(ext,types[i])) foundImage = YES;
- }
- if (foundImage) {
- // If the target file can be viewed as imageable data, we should
- // "morph" into an eTImage instance based on that file.
- // The code that eTImage would execute in this situation:
- // 1) create an imageComponent
- // 2) [self setImageComponent]
- self->isa = [eTImage class]; // assumes that we are a subclass of it
- [self setImageComponent: [[[eTImageComponent alloc]
- initInDoc:etDoc linked:NO]
- readComponentFromPath:buffer]];
- } else {
- // else we need to init etFileComponent _and_ attempt to initialize
- // eTImageComponent from buffer.tiff.
- self->isa = [eTFileLink class];
-
- etFileComponent = [[[eTComponent alloc] initInDoc:etDoc linked:NO]
- readComponentFromPath:buffer];
- strcat(buffer,".tiff"); //this is NeXT's default behavior
- [self setImageComponent: [[[eTImageComponent alloc]
- initInDoc:etDoc linked:NO]
- readComponentFromPath:buffer]] ;
- }
- return self;
- }
- @end